package com.coursehub.progress.service.impl;

import com.coursehub.progress.entity.StudentChapter;
import com.coursehub.progress.entity.StudentChapterId;
import com.coursehub.progress.entity.StudentMaterial;
import com.coursehub.progress.entity.StudentMaterialId;
import com.coursehub.progress.repository.StudentChapterRepository;
import com.coursehub.progress.repository.StudentMaterialRepository;
import com.coursehub.progress.service.StatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 统计分析服务实现类
 * 提供与单体系统StatisticsServiceImpl一致的功能
 */
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {
    
    private final StudentChapterRepository studentChapterRepository;
    private final StudentMaterialRepository studentMaterialRepository;
    private final RestTemplate restTemplate;
    
    @Value("${coursehub.services.urls.user-management}")
    private String userServiceUrl;
    
    @Value("${coursehub.services.urls.course-management}")
    private String courseServiceUrl;
    
    @Value("${coursehub.services.urls.exercise-management}")
    private String exerciseServiceUrl;
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getChapterIdsByStudentAndCourse(String studentId, String courseId) {
        try {
            // 验证学生是否选修了该课程
            String validateUrl = courseServiceUrl + "/courses/" + courseId + "/students/" + studentId + "/enrolled";
            Boolean isEnrolled = restTemplate.getForObject(validateUrl, Boolean.class);
            
            if (!Boolean.TRUE.equals(isEnrolled)) {
                throw new IllegalArgumentException("学生未选修该课程");
            }
            
            // 获取课程下的所有章节
            List<String> courseChapterIds = getChapterIdsByCourse(courseId);
            
            // 获取学生学习过的章节
            List<StudentChapter> studentChapters = studentChapterRepository.findByUserId(studentId);
            Set<String> studentChapterIds = studentChapters.stream()
                    .map(StudentChapter::getChapterId)
                    .collect(Collectors.toSet());
            
            // 过滤出属于该课程且学生学习过的章节ID
            return courseChapterIds.stream()
                    .filter(studentChapterIds::contains)
                    .collect(Collectors.toList());
                    
        } catch (Exception e) {
            log.error("获取学生课程章节ID失败: studentId={}, courseId={}, error={}", studentId, courseId, e.getMessage());
            throw new RuntimeException("获取学生课程章节ID失败", e);
        }
    }
    
    @Override
    public boolean validateStudentEnrollmentStatus(String studentId, String courseId) {
        try {
            String url = courseServiceUrl + "/courses/" + courseId + "/students/" + studentId + "/enrolled";
            Boolean isEnrolled = restTemplate.getForObject(url, Boolean.class);
            return Boolean.TRUE.equals(isEnrolled);
        } catch (Exception e) {
            log.error("验证学生选课状态失败: studentId={}, courseId={}", studentId, courseId, e);
            return false;
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getMaterialIdsByChapter(String chapterId) {
        try {
            String url = courseServiceUrl + "/materials/chapter/" + chapterId + "/ids";
            String[] materialIds = restTemplate.getForObject(url, String[].class);
            return materialIds != null ? Arrays.asList(materialIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取章节资料ID失败: chapterId={}, error={}", chapterId, e.getMessage());
            return Collections.emptyList();
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getChapterById(String chapterId) {
        try {
            String url = courseServiceUrl + "/chapters/" + chapterId;
            @SuppressWarnings("unchecked")
            Map<String, Object> chapter = restTemplate.getForObject(url, Map.class);
            if (chapter == null) {
                throw new IllegalArgumentException("章节不存在: " + chapterId);
            }
            return chapter;
        } catch (Exception e) {
            log.error("获取章节信息失败: chapterId={}, error={}", chapterId, e.getMessage());
            throw new RuntimeException("获取章节信息失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getCourseById(String courseId) {
        try {
            String url = courseServiceUrl + "/courses/" + courseId;
            @SuppressWarnings("unchecked")
            Map<String, Object> course = restTemplate.getForObject(url, Map.class);
            if (course == null) {
                throw new IllegalArgumentException("课程不存在: " + courseId);
            }
            return course;
        } catch (Exception e) {
            log.error("获取课程信息失败: courseId={}, error={}", courseId, e.getMessage());
            throw new RuntimeException("获取课程信息失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getMaterialById(String materialId) {
        try {
            String url = courseServiceUrl + "/materials/" + materialId;
            @SuppressWarnings("unchecked")
            Map<String, Object> material = restTemplate.getForObject(url, Map.class);
            if (material == null) {
                throw new IllegalArgumentException("资料不存在: " + materialId);
            }
            return material;
        } catch (Exception e) {
            log.error("获取资料信息失败: materialId={}, error={}", materialId, e.getMessage());
            throw new RuntimeException("获取资料信息失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getChapterIdsByCourse(String courseId) {
        try {
            String url = courseServiceUrl + "/chapters/course/" + courseId + "/ids";
            String[] chapterIds = restTemplate.getForObject(url, String[].class);
            return chapterIds != null ? Arrays.asList(chapterIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取课程章节ID失败: courseId={}, error={}", courseId, e.getMessage());
            return Collections.emptyList();
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getCourseProgress(String courseId, String studentId) {
        try {
            // 验证学生是否选修了该课程
            String validateUrl = courseServiceUrl + "/courses/" + courseId + "/students/" + studentId + "/enrolled";
            Boolean isEnrolled = restTemplate.getForObject(validateUrl, Boolean.class);
            
            if (!Boolean.TRUE.equals(isEnrolled)) {
                return 0; // 未选修该课程
            }
            
            List<String> chapterIds = getChapterIdsByCourse(courseId);
            
            if (chapterIds.isEmpty()) {
                return 100; // 没有章节视为已完成
            }
            
            int totalChapters = chapterIds.size();
            int completedChapters = 0;
            
            for (String chapterId : chapterIds) {
                StudentChapterId studentChapterId = new StudentChapterId(studentId, courseId, chapterId);
                Optional<StudentChapter> studentChapter = studentChapterRepository.findById(studentChapterId);
                if (studentChapter.isPresent() && studentChapter.get().getIsFinished()) {
                    completedChapters++;
                }
            }
            
            return (int) (((double) completedChapters / totalChapters) * 100);
            
        } catch (Exception e) {
            log.error("获取课程学习进度失败: courseId={}, studentId={}, error={}", courseId, studentId, e.getMessage());
            throw new RuntimeException("获取课程学习进度失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getChapterProgress(String chapterId, String studentId) {
        try {
            List<String> materialIds = getMaterialIdsByChapter(chapterId);
            
            if (materialIds.isEmpty()) {
                // 章节无资料时，直接通过 StudentChapter 表判断章节是否完成
                Map<String, Object> chapter = getChapterById(chapterId);
                String courseId = chapter != null ? (String) chapter.get("courseId") : null;
                StudentChapterId id = new StudentChapterId(studentId, courseId, chapterId);
                return studentChapterRepository.findById(id)
                        .filter(StudentChapter::getIsFinished)
                        .map(s -> 100)
                        .orElse(0);
            }
            
            int totalMaterials = materialIds.size();
            int completedMaterials = 0;
            
            // 通过 StudentMaterial 表查询学生对每个资料的完成状态
            Map<String, Object> chapter = getChapterById(chapterId);
            String courseId = chapter != null ? (String) chapter.get("courseId") : null;
            for (String materialId : materialIds) {
                StudentMaterialId smId = new StudentMaterialId(studentId, courseId, chapterId, materialId);
                Optional<StudentMaterial> studentMaterial = studentMaterialRepository.findById(smId);
                if (studentMaterial.isPresent() && studentMaterial.get().getIsFinished()) {
                    completedMaterials++;
                }
            }
            
            return (int) (((double) completedMaterials / totalMaterials) * 100);
            
        } catch (Exception e) {
            log.error("获取章节学习进度失败: chapterId={}, studentId={}, error={}", chapterId, studentId, e.getMessage());
            throw new RuntimeException("获取章节学习进度失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getMaterialProgress(String materialId, String studentId) {
        try {
            Map<String, Object> material = getMaterialById(materialId);
            String courseId = material != null ? (String) material.get("courseId") : null;
            String chapterId = material != null ? (String) material.get("chapterId") : null;
            StudentMaterialId id = new StudentMaterialId(studentId, courseId, chapterId, materialId);
            
            // 查询学生与资料的关联记录
            Optional<StudentMaterial> studentMaterial = studentMaterialRepository.findById(id);
            
            // 若存在记录且已完成，返回 100%；否则返回 0%
            return studentMaterial.map(sm -> sm.getIsFinished() ? 100 : 0).orElse(0);
            
        } catch (Exception e) {
            log.error("获取资料学习进度失败: materialId={}, studentId={}, error={}", materialId, studentId, e.getMessage());
            throw new RuntimeException("获取资料学习进度失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getClassCompletionRate(String classId) {
        try {
            // 获取班级对应的课程ID
            String courseId = getCourseIdByClassId(classId);
            if (courseId == null) {
                throw new IllegalArgumentException("课程不存在");
            }
            
            // 获取课程总章节数
            List<String> allChapterIds = getChapterIdsByCourse(courseId);
            int totalChapters = allChapterIds.size();
            if (totalChapters == 0) {
                return 100; // 课程没有章节
            }
            
            // 获取班级所有学生
            List<String> studentIds = getStudentIdsByClassId(classId);
            if (studentIds.isEmpty()) {
                return 0; // 班级没有学生
            }
            
            // 计算所有学生的完成章节总数
            int totalFinishedChapters = 0;
            for (String studentId : studentIds) {
                List<StudentChapter> studentProgress = studentChapterRepository.findByUserId(studentId);
                long finishedCount = studentProgress.stream()
                        .filter(progress -> allChapterIds.contains(progress.getChapterId()))
                        .filter(StudentChapter::getIsFinished)
                        .count();
                totalFinishedChapters += finishedCount;
            }
            
            // 计算班级完成比例
            // 公式：(所有学生完成的章节总数) / (课程章节总数 × 学生总数)
            int totalStudents = studentIds.size();
            return (int) ((totalFinishedChapters / (double) (totalChapters * totalStudents)) * 100);
            
        } catch (Exception e) {
            log.error("计算班级完成率失败: classId={}, error={}", classId, e.getMessage());
            throw new RuntimeException("计算班级完成率失败", e);
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public Integer getExerciseCompletionRate(String exerciseId) {
        try {
            // 获取练习信息及所属班级
            String url = exerciseServiceUrl + "/api/exercises/" + exerciseId;
            @SuppressWarnings("unchecked")
            Map<String, Object> exercise = restTemplate.getForObject(url, Map.class);
            if (exercise == null) {
                throw new IllegalArgumentException("练习不存在");
            }
            
            @SuppressWarnings("unchecked")
            Map<String, Object> classes = (Map<String, Object>) exercise.get("classes");
            if (classes == null) {
                throw new IllegalArgumentException("练习未关联到任何班级");
            }
            
            String classId = (String) classes.get("classesId");
            
            // 获取班级学生总数
            List<String> studentIds = getStudentIdsByClassId(classId);
            if (studentIds.isEmpty()) {
                return 0; // 班级没有学生
            }
            int totalStudents = studentIds.size();
            
            // 统计已提交该练习的学生数量
            String submissionUrl = exerciseServiceUrl + "/api/exercises/" + exerciseId + "/submissions/count";
            Integer submittedCount = restTemplate.getForObject(submissionUrl, Integer.class);
            if (submittedCount == null) {
                submittedCount = 0;
            }
            
            // 计算提交比例
            return (int) ((submittedCount / (double) totalStudents) * 100);
            
        } catch (Exception e) {
            log.error("计算练习完成率失败: exerciseId={}, error={}", exerciseId, e.getMessage());
            throw new RuntimeException("计算练习完成率失败", e);
        }
    }
    
    // 私有辅助方法
    
    private String getCourseIdByClassId(String classId) {
        try {
            String url = courseServiceUrl + "/classes/" + classId + "/course/id";
            return restTemplate.getForObject(url, String.class);
        } catch (Exception e) {
            log.error("获取班级课程ID失败: classId={}, error={}", classId, e.getMessage());
            throw new RuntimeException("获取班级课程ID失败", e);
        }
    }
    
    private List<String> getStudentIdsByClassId(String classId) {
        try {
            String url = courseServiceUrl + "/classes/" + classId + "/students/ids";
            String[] studentIds = restTemplate.getForObject(url, String[].class);
            return studentIds != null ? Arrays.asList(studentIds) : Collections.emptyList();
        } catch (Exception e) {
            log.error("获取班级学生ID失败: classId={}, error={}", classId, e.getMessage());
            return Collections.emptyList();
        }
    }
}